package cn.com.idmy.auth.oauth;

import cn.com.idmy.auth.context.Request;
import cn.com.idmy.auth.context.Response;
import cn.com.idmy.auth.exception.AuthException;
import cn.com.idmy.base.exception.UnauthorizedException;
import com.auth0.jwt.algorithms.Algorithm;
import org.dromara.hutool.core.text.StrUtil;
import org.jetbrains.annotations.NotNull;

public class OauthRefreshTokenImpl<ID> extends AbstractAccessToken<ID> {
    @Override
    public @NotNull AccessToken getToken(@NotNull Request request, @NotNull Response response) {
        var in = request.params().toJavaObject(RefreshToken.class);
        if (StrUtil.isBlank(in.clientId)) {
            var clientInfo = getClientInfoFromAuthorization(request.authorization());
            in.clientId = clientInfo.getLeft();
            in.clientSecret = clientInfo.getRight();
        }

        if (StrUtil.isBlank(in.refreshToken)) {
            throw new UnauthorizedException("刷新令牌不能为空");
        }

        var oauthClient = oauthManager.oauthClientDao.getOauthClient(in.clientId);
        if (!oauthClient.getGrantTypes().contains(GrantType.PASSWORD.name()) && StrUtil.isBlank(in.clientSecret)) {
            throw new AuthException("非密码模式 clientSecret 必须配置");
        }

        var pair = jwtTokenManager.parseToken(in.refreshToken);
        var cfgId = pair.getLeft();
        var token = pair.getRight();
        var cfg = tokenConfigDao.getTokenConfig(cfgId);

        var state = jwtTokenManager.parseToken((Algorithm) cfg.refreshTokenAlgorithm(), cfgId, token);
        state.config(cfg);
        state.principal(oauthManager.authenticator.getPrincipal(request, state.id()));

        oauthManager.loginManager.login(state);
        return new AccessToken()
                .accessToken(state.token())
                .exp(cfg.tokenExp().toSeconds())
                .refreshToken(state.refreshToken())
                .refreshExp(cfg.refreshTokenExp().toSeconds())
                .idToken(state.idToken());
    }
}
